#pragma once
#include<queue>
#include<pthread.h>

namespace wyl
{
    const size_t g_num = 5;
    template<class T>
    class ThreadPool
    {
    private:
        std::queue<T> queue_;
        pthread_mutex_t mutex_; //锁
        pthread_cond_t isempty_; //条件变量
        size_t num_; //线程池最大容量
        
    public:
        ThreadPool()
        {
            num_ = g_num;
            pthread_mutex_init(&mutex_,nullptr);
            pthread_cond_init(&isempty_,nullptr);
        }
        ~ThreadPool()
        {
            pthread_mutex_destroy(&mutex_);
            pthread_cond_destroy(&isempty_);
        }

        void ThreadPollInit()
        {
            pthread_t tid;
            for(int i = 0 ; i < num_; i++)
            {
                pthread_create(&tid,nullptr,Routine,this);
            }
        }

        void push(T& in)
        {
            //生产者生产
            Lock();
            queue_.push(in);
            Unlock();
            Wakeup();
        }

    private:
        static void* Routine(void* args)
        {
            pthread_detach(pthread_self());
            ThreadPool<T>* tp = (ThreadPool<T>*) args;

            tp->Lock();
            while(tp->is_empty())
            {
                tp->Wait();
            }
            //队列有任务，执行任务
            T t;
            tp->pop(&t);
            tp->Unlock();
            t.Run();
        }

        void pop(T* out)
        {
            //消费者消费
            *out = queue_.front();
            queue_.pop();
        }

        bool is_empty()
        {
            return queue_.size() == 0;
        }

        void Wait()
        {
            pthread_cond_wait(&isempty_,&mutex_);
        }
        void Wakeup()
        {
            pthread_cond_signal(&isempty_);
        }
        void Lock()
        {
            pthread_mutex_lock(&mutex_);
        }
        void Unlock()
        {
            pthread_mutex_unlock(&mutex_);
        }

    };
}